package com.micro.platform.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.platform.starter.component.PasswordEncoderComponent;
import com.micro.platform.starter.domain.PageFilter;
import com.micro.platform.starter.domain.PageResult;
import com.micro.platform.starter.utils.AssertUtil;
import com.micro.platform.starter.utils.BeanCopyUtil;
import com.micro.platform.user.controller.user.*;
import com.micro.platform.user.entity.Dept;
import com.micro.platform.user.entity.Role;
import com.micro.platform.user.entity.User;
import com.micro.platform.user.entity.UserRole;
import com.micro.platform.user.mapper.UserMapper;
import com.micro.platform.user.service.DeptService;
import com.micro.platform.user.service.RoleService;
import com.micro.platform.user.service.UserRoleService;
import com.micro.platform.user.service.UserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户-用户表 服务实现类
 * </p>
 *
 * @author zhouyk
 * @since 2021-12-06
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private DeptService deptService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    PasswordEncoderComponent passwordEncoderComponent;

    @Override
    public Boolean addUser(UserNewRequ userNewRequ) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getAccount, userNewRequ.getAccount());
        Integer integer = userMapper.selectCount(queryWrapper);
        AssertUtil.isTrue(integer == null ||  integer <= 0, "该账号用户已存在");
        User user = BeanCopyUtil.copyProperties(userNewRequ, User::new);
        try {
            user.setPassword(passwordEncoderComponent.encode(user.getPassword(), null));
        } catch (NoSuchAlgorithmException e) {
            AssertUtil.error("该账号密码加密失败");
        }
        int insert = userMapper.insert(user);
        Long id = user.getId();
        List<Long> roleIds = userNewRequ.getRoleIds();
        if(id != null && CollectionUtils.isNotEmpty(roleIds)){
            List<Long> roleIdsNonNull = roleIds.stream().filter(Objects::nonNull).collect(Collectors.toList());
            List<Role> rolesDb = roleService.getRolesByIds(roleIdsNonNull);
            List<Long> roleIdDbs = rolesDb.stream().map(Role::getId).collect(Collectors.toList());
            List<UserRole> lstUserRole = roleIdDbs.stream().map(roleIdDb ->{
                UserRole userRole = new UserRole();
                userRole.setUserId(id);
                userRole.setRoleId(roleIdDb);
                return userRole;
            }).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(lstUserRole)){
                userRoleService.saveBatch(lstUserRole);
            }
        }
        return insert > 0;
    }

    @Override
    public PageResult<UserInfosResp> pageFilter(PageFilter<UserPageFilterRequ> pageFilter) {
        UserPageFilterRequ filter = pageFilter.getFilter();
        QueryWrapper<User> pageFilterQueryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<User> lambda = pageFilterQueryWrapper.lambda();
        if(null != filter){
            if(StringUtils.isNotEmpty(filter.getName())){
                lambda.likeRight(User::getName, filter.getName());
            }
            if(StringUtils.isNotEmpty(filter.getEmail())){
                lambda.likeRight(User::getEmail, filter.getEmail());
            }
            if(StringUtils.isNotEmpty(filter.getPhone())){
                lambda.likeRight(User::getPhone, filter.getPhone());
            }
            if(StringUtils.isNotEmpty(filter.getAccount())){
                lambda.eq(User::getAccount, filter.getAccount());
            }
            if(null != filter.getDeptId()){
                Long deptId = filter.getDeptId();
                List<Dept> depts = deptService.getChildrenDeptsById(deptId);
                List<Long> deptIds = depts.stream().map(Dept::getId).collect(Collectors.toList());
                deptIds.add(deptId);
                lambda.in(User::getDeptId, deptIds);
            }
            lambda.eq(User::getHidden, Boolean.FALSE);
        }
        Page<User> page = userMapper.selectPage(pageFilter.toPage(), pageFilterQueryWrapper);
        PageResult<UserInfosResp> pageResult = PageResult.build(page, UserInfosResp::new);
        List<UserInfosResp> records = pageResult.getRecords();
        List<Long> userId = records.stream().map(UserInfosResp::getId).collect(Collectors.toList());
        List<UserRole> userRolesByUserIds = userRoleService.getUserRolesByUserIds(userId);
        Map<Long, List<Long>> mapUserId2RoleIds = userRolesByUserIds.stream().collect(Collectors.groupingBy(UserRole::getUserId, Collectors.mapping(UserRole::getRoleId, Collectors.toList())));
        for (UserInfosResp record : records) {
            Long id = record.getId();
            List<Long> longs = mapUserId2RoleIds.get(id);
            if(null == longs){
                longs = Collections.EMPTY_LIST;
            }
            record.setRoleIds(longs);
        }
        return pageResult;
    }

    @Override
    @Transactional
    public Boolean edited(UserEditedRequ userEditedRequ) {
        Long UserId = userEditedRequ.getId();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(User::getAccount, userEditedRequ.getAccount())
                .ne(User::getId, UserId);
        Integer integer = userMapper.selectCount(queryWrapper);
        AssertUtil.isTrue(integer == null ||  integer <= 0, "该账号用户已存在");
        User user = BeanCopyUtil.copyProperties(userEditedRequ, User::new);
        boolean update = this.updateById(user);
        List<Long> roleIds = userEditedRequ.getRoleIds();
        if(CollectionUtils.isNotEmpty(roleIds)){
            List<Long> roleIdsNonNull = roleIds.stream().filter(Objects::nonNull).collect(Collectors.toList());
            List<Role> rolesDb = roleService.getRolesByIds(roleIdsNonNull);
            List<Long> roleIdDbs = rolesDb.stream().map(Role::getId).collect(Collectors.toList());
            List<UserRole> lstUserRole = roleIdDbs.stream().map(roleIdDb ->{
                UserRole userRole = new UserRole();
                userRole.setUserId(UserId);
                userRole.setRoleId(roleIdDb);
                return userRole;
            }).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(lstUserRole)){
                userRoleService.UpdateBatch(lstUserRole, UserId);
            }
        }
        return update;
    }

    @Override
    public Boolean deleted(UserDeletedRequ userDeletedRequ) {
        Long id = userDeletedRequ.getId();
        boolean b = removeById(id);
        if(b){
            userRoleService.deletedUserRoleByUserId(id);
        }
        return b;
    }

    @Override
    public User getUserByAccount(String account) {
        if(StringUtils.isEmpty(account)){
            return null;
        }
        QueryWrapper<User>queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getAccount, account);
        return this.getOne(queryWrapper, Boolean.FALSE);
    }
}
